"use strict";

/**
 * 校验是否二代身份证号
 *
 * @since 0.0.4
 * @category 正则
 * @param {string|number} str 需要校验的字符串.
 * @param {object} config 配置参数.
 * @param {boolean} config.isDetail 是否返回详细信息, 为true时返回CheckResult, false时返回boolean 默认: false.
 * @param {boolean} config.isStrict 是否严格校验地址及校验码, 默认: true. 为false时, 仅校验18位数字或17位数字+X
 *
 * @returns { boolean|CheckResult } 校验结果 或 结果对象.
 *
 * @typedef {object} CheckResult
 * @property {boolean} status 校验结果
 * @property {string} errorMsg 错误提示
 *
 * @example
 *
 * z.isIdCard('53312119650528301X')
 * // => true
 *
 * z.isIdCard('533121196505283010', { isDetail: true })
 * // => { status: true, errorMsg: '' }
 *
 * z.isIdCard('533121196505283010', { isDetail: true, isStrict: true })
 * // => { status: false, errorMsg: '证件号码校验位错误' }
 */
function isIdCard(str) {
  var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
      _ref$isDetail = _ref.isDetail,
      isDetail = _ref$isDetail === void 0 ? false : _ref$isDetail,
      _ref$isStrict = _ref.isStrict,
      isStrict = _ref$isStrict === void 0 ? false : _ref$isStrict;

  var rt = {
    status: false,
    errorMsg: ''
  };
  if (typeof str === 'number') str = "".concat(str);
  var result = false;
  var msg = '';
  var city = {
    11: '北京',
    12: '天津',
    13: '河北',
    14: '山西',
    15: '内蒙古',
    21: '辽宁',
    22: '吉林',
    23: '黑龙江 ',
    31: '上海',
    32: '江苏',
    33: '浙江',
    34: '安徽',
    35: '福建',
    36: '江西',
    37: '山东',
    41: '河南',
    42: '湖北 ',
    43: '湖南',
    44: '广东',
    45: '广西',
    46: '海南',
    50: '重庆',
    51: '四川',
    52: '贵州',
    53: '云南',
    54: '西藏 ',
    61: '陕西',
    62: '甘肃',
    63: '青海',
    64: '宁夏',
    65: '新疆',
    71: '台湾',
    81: '香港',
    82: '澳门',
    91: '国外 '
  };

  if (!str) {
    msg = '证件号码不能为空';
  } else if (str.length === 18) {
    if (!/(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str)) {
      msg = '证件号码格式错误';
    } else if (!isStrict) {
      result = true;
    } else if (!city[str.substr(0, 2)]) {
      msg = '地址编码错误';
    } else {
      // 18位身份证需要验证最后一位校验位
      var strs = str.split(''); // ∑(ai×Wi)(mod 11)
      // 加权因子

      var factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]; // 校验位

      var parity = [1, 0, 'X', 9, 8, 7, 6, 5, 4, 3, 2, 'x'];
      var sum = 0;
      var ai = 0;
      var wi = 0;

      for (var i = 0; i < 17; i++) {
        ai = strs[i];
        wi = factor[i];
        sum += ai * wi;
      }

      if ("".concat(parity[sum % 11]) !== "".concat(strs[17])) {
        msg = '证件号码校验位错误';
      } else {
        result = true;
      }
    }
  } else {
    msg = '证件号码长度不为18位';
  }

  rt.errorMsg = msg;
  rt.status = result;
  return isDetail ? rt : rt.status;
}

module.exports = isIdCard;